package com.yuyou.fn.updater.handler;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.wens.mybatisplus.examples.Example;
import com.google.common.base.Optional;
import com.google.common.cache.LoadingCache;
import com.yuyou.fn.common.database.event.EventHandler;
import com.yuyou.fn.common.database.event.IEventHandler;
import com.yuyou.fn.common.util.CacheUtils;
import com.yuyou.fn.common.util.TimeUtils;
import com.yuyou.fn.common.util.Utils;
import com.yuyou.fn.educational.entity.ClassLecture;
import com.yuyou.fn.educational.entity.CourseClass;
import com.yuyou.fn.educational.entity.CourseTemplate;
import com.yuyou.fn.educational.entity.Teacher;
import com.yuyou.fn.educational.service.IClassLectureService;
import com.yuyou.fn.educational.service.ICourseClassService;
import com.yuyou.fn.educational.service.ICourseTemplateService;
import com.yuyou.fn.educational.service.ITeacherService;
import com.yuyou.fn.report.entity.ClassLectureDetail;
import com.yuyou.fn.report.service.IClassLectureDetailService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ExecutionException;

@EventHandler(tables = {"yyfn.course_class","yyfn.class_lecture"})
@Component
public class ClassLectureDetailUpdater implements IEventHandler {

    private final static Logger log = LoggerFactory.getLogger(ClassLectureDetailUpdater.class);

    @Resource
    private ICourseTemplateService courseTemplateService;

    @Resource
    private ICourseClassService courseClassService;

    @Resource
    private IClassLectureDetailService classLectureDetailService;

    @Resource
    private ITeacherService teacherService;

    @Resource
    private IClassLectureService classLectureService;

    private LoadingCache<Long,Optional<CourseTemplate>> loadingCacheOfCourseTemplate ;
    private LoadingCache<Long,Optional<CourseClass>> loadingCacheOfCourseClass ;
    private LoadingCache<Long,Optional<Teacher>> teacherLoadingCache ;

    @PostConstruct
    public void init(){

        this.loadingCacheOfCourseTemplate = CacheUtils.buildCache(courseTemplateService::findById);
        this.loadingCacheOfCourseClass = CacheUtils.buildCache(courseClassService::findById);
        this.teacherLoadingCache = CacheUtils.buildCache(teacherService::findById) ;

    }


    @Override
    public void insert(String tableName, JSONArray rowList) {

        if(tableName.contains("class_lecture")){
            try {
                buildClassLectureDetail(rowList);
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            }
        }
    }

    @Override
    public void update(String tableName, JSONArray rowList, Set<String> updateColumns) {

        if(tableName.contains("class_lecture")){
            try {
                buildClassLectureDetail(rowList);
                if (updateColumns.contains("class_date") || updateColumns.contains("start_time") || updateColumns.contains("end_time")) {
                    for (int i = 0; i < rowList.size(); i++) {
                        JSONObject row = rowList.getJSONObject(i);
                        updateClass(row);
                    }
                }

            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            }
        }else if(tableName.contains("course_class")){

            for (int i = 0; i < rowList.size(); i++) {
                JSONObject row = rowList.getJSONObject(i);
                try{
                    updateByCourseClass(row);
                }catch (Exception e){
                    log.error("updateByCourseClass fail" , e );
                }

            }

        }
    }

    private void updateByCourseClass(JSONObject row) {
        CourseClass courseClass = row.toJavaObject(CourseClass.class);

        ClassLectureDetail classLectureDetail = new ClassLectureDetail();
        classLectureDetail.setClassName(courseClass.getClassName());
        classLectureDetail.setGradeId(courseClass.getGradeId());
        classLectureDetail.setGradeName(courseClass.getGradeName());
        classLectureDetail.setSubjectId(courseClass.getSubjectId());
        classLectureDetail.setSubjectName(courseClass.getSubjectName());
        classLectureDetail.setSeniorId(courseClass.getSeniorId());
        classLectureDetail.setSeniorName(courseClass.getSeniorName());
        classLectureDetail.setPeriodId(courseClass.getPeriodId());
        classLectureDetail.setAreaTeamId(courseClass.getAreaTeamId());
        classLectureDetail.setBusTeamId(courseClass.getBusTeamId());
        classLectureDetail.setCampusId(courseClass.getCampusId());
        classLectureDetail.setCampusName(courseClass.getCampusName());
        classLectureDetail.setStatus(courseClass.getStatus());
        classLectureDetail.setAreaTeamName(courseClass.getAreaTeamName());
        classLectureDetail.setBusTeamName(courseClass.getBusTeamName());
        classLectureDetail.setClassNo(courseClass.getClassNo());
        classLectureDetail.setPeriodName(courseClass.getPeriodName());
        classLectureDetail.setLectureAmount(courseClass.getLectureAmount());
        classLectureDetail.setSegmentNo(courseClass.getSegmentNo());
        Example<ClassLectureDetail> example = ClassLectureDetail.createExample();
        example.createCriteria().andEqualTo("classId",courseClass.getClassId());

        classLectureDetailService.updateSelectiveByExample(classLectureDetail, example );
    }

    @Override
    public void delete(String tableName, JSONArray rowList) {

        if(tableName.contains("class_lecture")){
            List<Long> classLectureIds  = new ArrayList<>(rowList.size());
            for (int i = 0; i < rowList.size(); i++) {
                JSONObject row = rowList.getJSONObject(i);
                classLectureIds.add(row.getLong("classLectureId"));

            }
            classLectureDetailService.deleteBatchIds(classLectureIds);
        }
    }

    private void buildClassLectureDetail(JSONArray rowList) throws ExecutionException {

        for (int i = 0; i < rowList.size(); i++) {
            JSONObject row = rowList.getJSONObject(i);
            saveOrUpdate(row);
        }

    }

    private void saveOrUpdate(JSONObject row) throws ExecutionException {
        ClassLecture classLecture = row.toJavaObject(ClassLecture.class);

        CourseClass courseClass = loadingCacheOfCourseClass.get(classLecture.getClassId()).get();

        CourseTemplate courseTemplate = loadingCacheOfCourseTemplate.get(courseClass.getCourseTemplateId()).get();

        Teacher teacher= null;//teacherLoadingCache.get(classLecture.getTeacherId()).get();
        if (classLecture.getTeacherId()!=null && teacherLoadingCache.get(classLecture.getTeacherId())!=null){
            teacher=teacherLoadingCache.get(classLecture.getTeacherId()).get();
        }

        ClassLectureDetail classLectureDetail = new ClassLectureDetail();
        classLectureDetail.setClassLectureDetailId(classLecture.getClassLectureId());
        classLectureDetail.setClassId(classLecture.getClassId());
        classLectureDetail.setClassName(courseClass.getClassName());
        classLectureDetail.setGradeId(courseClass.getGradeId());
        classLectureDetail.setGradeName(courseClass.getGradeName());
        classLectureDetail.setSubjectId(courseClass.getSubjectId());
        classLectureDetail.setSubjectName(courseClass.getSubjectName());
        classLectureDetail.setSeniorId(courseClass.getSeniorId());
        classLectureDetail.setSeniorName(courseClass.getSeniorName());
        classLectureDetail.setPeriodId(courseClass.getPeriodId());
        classLectureDetail.setAreaTeamId(courseClass.getAreaTeamId());
        classLectureDetail.setBusTeamId(courseClass.getBusTeamId());
        classLectureDetail.setCampusId(courseClass.getCampusId());
        classLectureDetail.setCampusName(courseClass.getCampusName());
        classLectureDetail.setStatus(courseClass.getStatus());
        classLectureDetail.setAreaTeamName(courseClass.getAreaTeamName());
        classLectureDetail.setBusTeamName(courseClass.getBusTeamName());
        classLectureDetail.setClassNo(courseClass.getClassNo());
        classLectureDetail.setPeriodName(courseClass.getPeriodName());
        classLectureDetail.setClassLectureId(classLecture.getClassLectureId());
        classLectureDetail.setLectureNo(classLecture.getLectureNo());
        classLectureDetail.setStartTime(classLecture.getStartTime());
        classLectureDetail.setEndTime(classLecture.getEndTime());
        classLectureDetail.setClassDate(classLecture.getClassDate());
        classLectureDetail.setTeacherId(classLecture.getTeacherId());
        if(teacher != null ){
            classLectureDetail.setTeacherName(teacher.getTeacherName());
            classLectureDetail.setJobNature(teacher.getJobNature().intValue());
        }

        classLectureDetail.setCourseTemplateId(courseTemplate.getCourseTemplateId());
        classLectureDetail.setCourseName(courseTemplate.getCourseName());
        classLectureDetail.setProductId(courseTemplate.getProductId());
        classLectureDetail.setProductName(courseTemplate.getProductName());
        classLectureDetail.setSegmentNo(courseClass.getSegmentNo());
        try{
            classLectureDetailService.insertSelective(classLectureDetail);
        }catch (Exception e){
            classLectureDetailService.updateById(classLectureDetail);
        }
    }


    private void updateClass(JSONObject row){
        ClassLecture classLecture = row.toJavaObject(ClassLecture.class);
        List<ClassLecture> classLectureList=classLectureService.findClassLectureByClassId(classLecture.getClassId());
        if (Utils.checkListEmpty(classLectureList)){
            return;
        }
        TreeSet<String> studyingSet=new TreeSet<>();
        CourseClass courseClass=new CourseClass();
        courseClass.setClassId(classLecture.getClassId());
        courseClass.setStartCourseTime(classLectureList.get(0).getClassDate());
        courseClass.setEndCourseTime(classLectureList.get(classLectureList.size()-1).getClassDate());
        for (ClassLecture one:classLectureList){
            if(StringUtils.isNotEmpty(one.getStartTime()) && StringUtils.isNotEmpty(one.getEndTime())){
                String studyingTime=one.getStartTime()+"-"+one.getEndTime();
                studyingSet.add(studyingTime);
            }
        }
        courseClass.setStudyingTime(StringUtils.join(studyingSet," "));
        courseClass.setUpdateTime(TimeUtils.now());
        courseClassService.updateSelectiveById(courseClass);
    }

    public static void main(String[] args) {
        Method[] methods = ClassLectureDetail.class.getDeclaredMethods();
        for(Method method : methods ){
            if(method.getName().startsWith("set")){
                System.out.println("classLectureDetail." + method.getName() );
            }
        }
    }
}
